using System.IO;
using System.Collections;
using System.Text;
using iTextSharp.text.rtf.document;
using FD = iTextSharp.text.rtf.field;

namespace iTextSharp.text.rtf.text
{

    /// <summary>
    /// The RtfSection wraps a Section element.
    /// INTERNAL CLASS
    /// @author Mark Hall (Mark.Hall@mail.room3b.eu)
    /// </summary>
    public class RtfSection : RtfElement
    {

        /// <summary>
        /// The sub-items of this RtfSection
        /// </summary>
        protected ArrayList Items;

        /// <summary>
        /// The title paragraph of this RtfSection
        /// </summary>
        protected RtfParagraph Title;

        /// <summary>
        /// Constructs a RtfSection for a given Section. If the autogenerateTOCEntries
        /// property of the RtfDocument is set and the title is not empty then a TOC entry
        /// is generated for the title.
        /// </summary>
        /// <param name="doc">The RtfDocument this RtfSection belongs to</param>
        /// <param name="section">The Section this RtfSection is based on</param>
        public RtfSection(RtfDocument doc, Section section) : base(doc)
        {
            Items = new ArrayList();
            try
            {
                if (section.Title != null)
                {
                    Title = (RtfParagraph)doc.GetMapper().MapElement(section.Title)[0];
                }
                if (Document.GetAutogenerateTocEntries())
                {
                    StringBuilder titleText = new StringBuilder();
                    foreach (IElement element in section.Title)
                    {
                        if (element.Type == Element.CHUNK)
                        {
                            titleText.Append(((Chunk)element).Content);
                        }
                    }
                    if (titleText.ToString().Trim().Length > 0)
                    {
                        FD.RtfTocEntry tocEntry = new FD.RtfTocEntry(titleText.ToString());
                        tocEntry.SetRtfDocument(Document);
                        Items.Add(tocEntry);
                    }
                }
                foreach (IElement element in section)
                {
                    IRtfBasicElement[] rtfElements = doc.GetMapper().MapElement(element);
                    for (int i = 0; i < rtfElements.Length; i++)
                    {
                        if (rtfElements[i] != null)
                        {
                            Items.Add(rtfElements[i]);
                        }
                    }
                }
                updateIndentation(section.IndentationLeft, section.IndentationRight, section.Indentation);
            }
            catch (DocumentException)
            {
            }
        }

        /// <summary>
        /// Sets whether this RtfSection is in a header. Sets the correct inTable setting for all
        /// child elements.
        /// </summary>
        /// <param name="inHeader"> True  if this RtfSection is in a header,  false  otherwise</param>
        public override void SetInHeader(bool inHeader)
        {
            base.SetInHeader(inHeader);
            for (int i = 0; i < Items.Count; i++)
            {
                ((IRtfBasicElement)Items[i]).SetInHeader(inHeader);
            }
        }

        /// <summary>
        /// Sets whether this RtfSection is in a table. Sets the correct inTable setting for all
        /// child elements.
        /// </summary>
        /// <param name="inTable"> True  if this RtfSection is in a table,  false  otherwise</param>
        public override void SetInTable(bool inTable)
        {
            base.SetInTable(inTable);
            for (int i = 0; i < Items.Count; i++)
            {
                ((IRtfBasicElement)Items[i]).SetInTable(inTable);
            }
        }

        /// <summary>
        /// Write this RtfSection and its contents
        /// </summary>
        public override void WriteContent(Stream result)
        {
            result.Write(RtfParagraph.Paragraph, 0, RtfParagraph.Paragraph.Length);
            if (Title != null)
            {
                Title.WriteContent(result);
            }
            foreach (IRtfBasicElement rbe in Items)
            {
                rbe.WriteContent(result);
            }
        }
        /// <summary>
        /// Updates the left, right and content indentation of all RtfParagraph and RtfSection
        /// elements that this RtfSection contains.
        /// </summary>
        /// <param name="indentLeft">The left indentation to add.</param>
        /// <param name="indentRight">The right indentation to add.</param>
        /// <param name="indentContent">The content indentation to add.</param>
        private void updateIndentation(float indentLeft, float indentRight, float indentContent)
        {
            if (Title != null)
            {
                Title.SetIndentLeft((int)(Title.GetIndentLeft() + indentLeft * TWIPS_FACTOR));
                Title.SetIndentRight((int)(Title.GetIndentRight() + indentRight * TWIPS_FACTOR));
            }
            for (int i = 0; i < Items.Count; i++)
            {
                IRtfBasicElement rtfElement = (IRtfBasicElement)Items[i];
                if (rtfElement is RtfSection)
                {
                    ((RtfSection)rtfElement).updateIndentation(indentLeft + indentContent, indentRight, 0);
                }
                else if (rtfElement is RtfParagraph)
                {
                    ((RtfParagraph)rtfElement).SetIndentLeft((int)(((RtfParagraph)rtfElement).GetIndentLeft() + (indentLeft + indentContent) * TWIPS_FACTOR));
                    ((RtfParagraph)rtfElement).SetIndentRight((int)(((RtfParagraph)rtfElement).GetIndentRight() + indentRight * TWIPS_FACTOR));
                }
            }
        }
    }
}